<?php

namespace wchat\common;

use Exception;
use JetBrains\PhpStorm\ArrayShape;
use Kiri\Client;

/**
 * Class Result
 *
 * @package app\components
 *
 * @property $code
 * @property $message
 * @property $count
 * @property $data
 */
class Result
{

    private ?int $startTime;
    private ?int $requestTime;
    private ?int $runTime;

    /**
     * @param int $code
     * @param string $message
     * @param int $count
     * @param mixed $data
     * @param array $header
     */
    public function __construct(public int $code, public string $message = '', public int $count = 0, public mixed $data = [], public array $header = [],)
    {
    }


    /**
     * @param string $data
     * @return static
     */
    public static function wxInit(string $data): static
    {
        $json = json_decode($data, true);
        if (isset($json['errcode']) && $json['errcode'] != 0) {
            return new Result(code: $json['errcode'], message: $json['errmsg']);
        } else {
            return new Result(code: 0, data: $json);
        }
    }


    /**
     * @param Client $client
     * @return static
     */
    public static function init(Client $client): static
    {
        if (!in_array($client->getStatusCode(), [101, 200, 201])) {
            return new Result(code: 505, message: $client->getBody());
        }
        $body = json_decode($client->getBody(), true);
        if (isset($body['errcode']) && $body['errcode'] != 0) {
            return new Result(code: $body['errcode'], message: $body['errmsg']);
        } else {
            return new Result(code: 0, data: $body);
        }
    }


    /**
     * @param $name
     * @return mixed
     */
    public function __get($name)
    {
        return $this->$name;
    }


    /**
     * @param $name
     * @param $value
     * @return $this
     */
    public function __set($name, $value)
    {
        $this->$name = $value;

        return $this;
    }

    /**
     * @return array
     */
    #[ArrayShape(['startTime' => "int|null", 'requestTime' => "int|null", 'runTime' => "int|null"])]
    public function getTime(): array
    {
        return [
            'startTime'   => $this->startTime,
            'requestTime' => $this->requestTime,
            'runTime'     => $this->runTime,
        ];
    }

    /**
     * @param $key
     * @param $data
     * @return $this
     * @throws
     */
    public function setAttr($key, $data): static
    {
        if (!property_exists($this, $key)) {
            throw new Exception('未查找到相应对象属性');
        }
        $this->$key = $data;
        return $this;
    }

    /**
     * @return bool
     */
    public function isResultsOK(): bool
    {
        if (!is_numeric($this->code)) {
            return false;
        }
        return $this->code == 0;
    }


    /**
     * @param string $name
     * @return mixed
     */
    public function getData(string $name = ''): mixed
    {
        if (!$this->isResultsOK()) {
            return $this->data;
        }
        if (!is_array($this->data)) {
            return $this->data;
        }
        if ($name != '') {
            return $this->data[$name] ?? null;
        } else {
            return $this->data;
        }
    }

    /**
     * @param $key
     * @param $data
     * @return $this
     */
    public function append($key, $data): static
    {
        if (!is_array($this->data)) {
            $this->data = ['origin' => $this->data];
        }
        $this->data[$key] = $data;
        return $this;
    }

    /**
     * @return string
     */
    public function getMessage(): string
    {
        return $this->message;
    }

    /**
     * @return int
     */
    public function getCode(): int
    {
        return $this->code;
    }
}
